package com.caijg.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.dashscope.app.Application;
import com.alibaba.dashscope.app.ApplicationParam;
import com.alibaba.dashscope.app.ApplicationResult;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.caijg.domain.dto.UserMessageDTO;
import com.caijg.domain.po.Chat;
import com.caijg.domain.pojo.Message;
import com.caijg.domain.vo.ChatVO;
import com.caijg.domain.vo.Result;
import com.caijg.mapper.ChatMapper;
import com.caijg.service.IChatService;
import com.caijg.service.IPromptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

import static com.caijg.utils.Constant.*;


/**
 * <p>
 * 对话表 服务实现类
 * </p>
 *
 * @author caijg
 * @since 2024-12-26
 */
@Service
@Slf4j
public class ChatServiceImpl extends ServiceImpl<ChatMapper, Chat> implements IChatService {

    @Autowired
    private IPromptService promptService;

    @Override
    public Result chat(UserMessageDTO userMessageDTO) {

        // 1.设置访问大模型的参数
        ApplicationParam.ApplicationParamBuilder<?, ?> o = ApplicationParam.builder()
                // 设置调用的密钥
                .appId(APP_ID)
                .apiKey(API_KEY);

        // 2.如果是新对话，给大模型提示词
        if (StringUtils.isBlank(userMessageDTO.getSessionId())) {
            o.prompt(promptService.getPromptByName(CHAT_PROMPT_NAME));
        } else {
            // 3.如果是老对话，指定sessionid并直接喂给大模型“用户输入的内容”
            o.sessionId(userMessageDTO.getSessionId())
                    .prompt(userMessageDTO.getContent());
        }

        // 4.构造大模型访问参数
        ApplicationParam param = o.build();

        Application application = new Application();
        ApplicationResult result = null;
        try {
            // 5.调用大模型拿到结果
            result = application.call(param);
        } catch (NoApiKeyException | InputRequiredException e) {
            throw new RuntimeException(e);
        }

        String answer = result.getOutput().getText();
        String sId = result.getOutput().getSessionId();
        // 6.存到MySQL
        Chat chat = this.query()
                .eq("session_id", sId)
                .one();
        // 如果该对话不存在，创建对话并存入数据库
        if (chat == null) {
            // 把用户提问+AI回答存到JSON数组里面
            JSONArray records = JSONUtil.createArray();
            records.add(new Message("user", userMessageDTO.getContent()));
            records.add(new Message("ai", answer));

            // 创建一个chat对象
            chat = new Chat();
            chat.setSessionId(sId);
            chat.setUserId(userMessageDTO.getUserId());
            chat.setRecords(records.toString());
            chat.setLastQuestion(userMessageDTO.getContent());
            chat.setUpdateTime(LocalDateTime.now());
            chat.setCreateTime(LocalDateTime.now());

            // 存入数据库
            this.save(chat);
        } else {
            // 如果该对话存在，更新对话记录并存入数据库
            JSONArray records = JSONUtil.parseArray(chat.getRecords());
            records.add(new Message("user", userMessageDTO.getContent()));
            records.add(new Message("ai", answer));
            chat.setRecords(records.toString());
            chat.setLastQuestion(userMessageDTO.getContent());
            chat.setUpdateTime(LocalDateTime.now());
            this.updateById(chat);
        }

        // 7. 返回结果
        ChatVO chatVO = new ChatVO(answer, sId);
        return Result.success(chatVO);
    }

    @Override
    public Result history(String userId) {
        List<Chat> chatList = this.lambdaQuery()
                .eq(Chat::getUserId, userId)
                .orderByDesc(Chat::getUpdateTime)
                .list();

        return Result.success(chatList);
    }

    @Override
    public Result messages(String sessionId) {
        Chat chat = this.lambdaQuery()
                .eq(Chat::getSessionId, sessionId)
                .one();

        if (chat == null) {
            return Result.error(404, "对话记录不存在");
        }

        return Result.success(chat.getRecords());
    }

    @Override
    public Result delete(String sessionId) {
        boolean ok = this.lambdaUpdate()
                .eq(Chat::getSessionId, sessionId)
                .remove();
        if (!ok) {
            return Result.error(500, "删除失败");
        }

        return Result.success();
    }
}
